#usr/bin/env python3
#coding:utf-8
import re
import time,datetime
from twisted.internet.threads import deferToThread


def gumi_first_handle(data,self):
	data_handled=[]
	buffer_data_in=[]
	data=bytes.hex(data)
	# 定义数据处理的递归函数
	def get_whole_pack(data,buffer_data_in,data_handled):
		# 数据包如果以6767开头，进行数据处理，否则放入data_buffer
		if data.startswith('6767'):
			rule=r'(?P<data_head>\w{4})(?P<mesg_id>\w{2})(?P<data_len>\w{4})(?P<data_num>\w{4})'
			head_data=re.search(rule,data)
			head_data_dict=head_data.groupdict()
			
			# 数据包描述的长度
			data_len=int(head_data_dict['data_len'],16)
			
			# 实际的数据体
			body_data=data[len(head_data.group()):]
			data_detail=data[len(head_data.group()):]
			# 数据的实际长度
			real_len=len(data_detail+head_data_dict['data_num'])/2
			# print('check--------',real_len,data_len)
			# 数据包描述的长度和实际长度不等的，进行递归处理，
			if real_len!=data_len:
				# 实际长度小于信息包描述长度,放入buffer_data
				if real_len<data_len:
					# print('real_len<data_len----------------')
					buffer_data_in.append(bytes.fromhex(data))
				# 实际长度大于数据包描述长度，把实际长度的数据切割取出，放入twisted线程进行数据解析处理，多余的数据，进行递归处理
				elif real_len>data_len:
					one_pack=head_data.group()+body_data[0:data_len*2-4]
					deferToThread(self.handle_data,one_pack).addCallback(self.write_response)
					rest_data=data[len(one_pack):]
					# print('rest_data-----',rest_data)
					get_whole_pack(rest_data,buffer_data_in,data_handled)
					# return {'normal_data':data_handled,'buffer_data':rest_data}
			else:
				# 6767开头，而且实际长度和描述长度相等的数据包，放入twisted线程进行数据解析处理
				deferToThread(self.handle_data,data).addCallback(self.write_response)
		else:
			# print('data-not-startswith(6767)--------',data)
			buffer_data_in.append(bytes.fromhex(data))

	# 开启数据解析处理的递归函数
	get_whole_pack(data,buffer_data_in,data_handled)

	# 经过递归函数处理的数据包，如果有剩余的数据，作为结果返回，让外层调用的语句把剩余数据放入data_buffer,
	if buffer_data_in==[]:
		buffer_data_in='0'

	return buffer_data_in



def handle_location_package(data_detail):
	rule=r'(?P<time_data>\w{8})(?P<lat>\w{8})(?P<lng>\w{8})(?P<speed>\w{2})(?P<dirct>\w{4})(?P<lbs>\w{18})(?P<status>\w{2})'
	data_result=re.search(rule,data_detail)
	data_result=data_result.groupdict()
	time_data=int(data_result['time_data'],16)
	data_result['dev_upload']=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time_data))
	data_result['lng']=round((int(data_result['lng'],16)/30000)/60,4)
	data_result['lat']=round((int(data_result['lat'],16)/30000)/60,4)
	data_result['speed']=int(data_result['speed'],16)
	data_result['dirct']=int(data_result['dirct'],16)
	data_result['lbs']=str({'MCC':int(data_result['lbs'][0:4],16),'MNC':int(data_result['lbs'][4:8],16),'sid':int(data_result['lbs'][8:12],16),'nid':int(data_result['lbs'][12:18],16)})
	s0='{:08b}'.format(int(data_result['status'],16))

	track_status='track'
	acc_status='acc_on'
	if s0[6]=='0':
		acc_status='acc_off'
	if s0[7]=='0':
		 track_status='untrack'

	data_result['status']=str([track_status,acc_status])

	return data_result


def gumi_analysis(data):
	all_data={}
	response=b'0'
	all_data['device_model']='gumi'
	if data=='':
		all_data['response']=b'0'
		return all_data
	rule=r'(?P<data_head>\w{4})(?P<mesg_id>\w{2})(?P<data_len>\w{4})(?P<data_num>\w{4})'
	head_data=re.search(rule,data)
	head_data_dict=head_data.groupdict()
	
	data_len=int(head_data_dict['data_len'],16)
	
	# 具体数据内容,判断长度是否符合
	body_data=data[len(head_data.group()):]
	data_detail=data[len(head_data.group()):]
	real_len=len(data_detail+head_data_dict['data_num'])/2
	# print('check--------',real_len,data_len)

	# 结果填入
	all_data.update(head_data_dict)
	# 统一回复
	response='6767'+head_data_dict['mesg_id']+'0002'+head_data_dict['data_num']
	response=bytes.fromhex(response)

	# 数据头
	mesg_id=head_data_dict['mesg_id']
	# 登录包
	if mesg_id=='01':
		print(data_detail)
		rule=r'(?P<device_id>\w{16})(?P<language>\w{2})'
		data_result=re.search(rule,data_detail)
		device_id=str(int(data_result['device_id']))
		language_dict={'00':'chinese','01':'english'}
		language=language_dict[data_result['language']]
		all_data.update(device_id=device_id,language=language)


	elif mesg_id=='02':
		data_result=handle_location_package(data_detail)
		all_data.update(data_result)
		response=b'0'
	elif mesg_id=='03':
		rule=r'(?P<status>\w{4})'
		data_result=re.search(rule,data_detail)
		s0='{:16b}'.format(int(data_result['status'],16))
		track_status='track'
		acc_status='no_acc'
		defence='no_defence'
		oil_ele='no_oil_ele'
		charge='no_charge_on'

		if s0[15]=='0':
			track_status='untrack'

		if s0[-2:-4]=='10':
			acc_status='acc_off'
		elif s0[-2:-4]=='11':
			acc_status='acc_on'

		if s0[-4:-6]=='10':
			acc_status='defence_off'
		elif s0[-4:-6]=='11':
			acc_status='defence_on'

		if s0[-6:-8]=='10':
			acc_status='oil_ele_off'
		elif s0[-6:-8]=='11':
			acc_status='oil_ele_on'

		if s0[-6:-8]=='10':
			acc_status='charge_off'
		elif s0[-6:-8]=='11':
			acc_status='charge_on'

		status=str([track_status,acc_status,defence,oil_ele,charge])
		all_data['status']=status

	elif mesg_id=='04':
		data_result=handle_location_package(data_detail)
		rule=r'(?P<time_data>\w{8})(?P<lat>\w{8})(?P<lng>\w{8})(?P<speed>\w{2})(?P<direct>\w{4})(?P<lbs>\w{18})(?P<status>\w{2})(?P<alarm_status>\w{2})'
		alarm_status=re.search(rule,data_detail).groupdict()['alarm_status']
		alarm_dict={'01':'power_off','02':'sos_alarm','03':'low_power','04':'quake_alarm','05':'move_alarm','06':'entry_blind','07':'out_blind',
					'08':'ante_apart','09':'ante_short','0a':'light_alarm','0b':'magnet_alarm','0c':'remove_alarm','0d':'speed_alarm',
					'0e':'signal_shield_alarm','0f':'fake_station_alarm','10':'out_ele_low','11':'out_ele_heigh','12':'hit_alarm',
					'13':'rapid_acceleration','14':'rapid_brake','15':'over_turn','16':'rapid_turn','17':'caidong_alarm'}
		# print(re.search(rule,data_detail).groupdict())
		data_result['alarm_mesg']=str([alarm_dict[alarm_status]])
		all_data.update(data_result)

		# 报警信息需要发给指定的手机号码内容的，进行特殊回复，加入需要发送的信息内容，暂时不需要发送信息内容给手机
		# response=response+bytes.fromhex(alarm_status)
		# response='6767'+mesg_id+'0002'+head_data_dict['data_num']

	elif mesg_id=='05':
		data_result=handle_location_package(data_detail)
		rule=r'(?P<time_data>\w{8})(?P<lat>\w{8})(?P<lng>\w{8})(?P<speed>\w{2})(?P<direct>\w{4})(?P<lbs>\w{18})(?P<status>\w{2})(?P<status_kind>\w{2})'

		status_kind=re.search(rule,data_detail).groupdict('status_kind')
		status_kind_dict={'01':'acc_launch','02':'acc_close'}
		status_kind=status_kind_dict[status_kind]
		dev_time_data=data_detail(len(re.search(rule,data_detail).group()))
		dev_time_data=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float(dev_time_data)))
		data_result['dev_status']=str([status_kind,dev_time_data])

		response=b'0'

	elif mesg_id=='06':
		data_result=handle_location_package(data_detail)
		rule=r'(?P<time_data>\w{8})(?P<lat>\w{8})(?P<lng>\w{8})(?P<speed>\w{2})(?P<direct>\w{4})(?P<lbs>\w{18})(?P<status>\w{2})'
		second_hanlde=re.search(rule,data_detail)
		second_data=data_detail[len(second_hanlde.group()):]
		phone_num=second_data[0:42]
		sms_detail=sms_detail[42:]
		# print(phone_num,sms_detail)

		all_data.update(data_result)

		mesg_len='%04x' % int(phone_num+head_data['data_num'],16)
		response='6767'+mesg_id+mesg_len+head_data['data_num']+phone_num
		response=bytes.fromhex(response)

		# response=response+bytes.fromhex(second_data)

	elif mesg_id=='91':
		rule=r'(?P<time_data>\w{8})(?P<ta>\w{8})(?P<MCC>\w{8})(?P<MNC>\w{2})(?P<lbs_num>\w{4})(?P<lbs>\w{60})(?P<status>\w{2})'
		data_result=re.search(rule,data_detail).groupdict()
		data_result['time_data']=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float(data_result['time_data'])))
		lbs_num=data_result['lbs_num']
		lbs=data_result['lbs']
		lbs_list=[]
		MNC=data_result.pop('MNC')
		MCC=data_result.pop('MCC')
		for x in range(int(lbs_num)):
			lbs_data=lbs[x*6:(x+1)*6]
			lbs_dict={'MNC':int(MNC,16),'MCC':int(MCC,16),'sid':int(lbs_data[0:4],16),'nid':int(lbs_data[4:10],16),'rssi':lbs_data[10:12]}
			lbs_list.append(lbs_dict)


		s0='{:08b}'.format(int(data_result['status'],16))

		track_status='track'
		send_kind='sms_send'
		if s0[6]=='0':
			send_kind='dev_send'
		if s0[7]=='0':
			 track_status='untrack'

		data_result['status']=str([track_status,acc_status])

		response=b'0'

	elif mesg_id=='07':
		rule=r'(?P<status>\w{4})(?P<gsm>\w{2})(?P<battery>\w{2})'
		data_result=re.search(rule,data_detail)

		s0='{:16b}'.format(int(data_result['status'],16))

		track_status='track'
		acc_status='no_acc'
		defence='no_defence'
		oil_ele='no_oil_ele'
		charge='no_charge_on'

		if s0[15]=='0':
			track_status='untrack'

		if s0[-2:-4]=='10':
			acc_status='acc_off'
		elif s0[-2:-4]=='11':
			acc_status='acc_on'

		if s0[-4:-6]=='10':
			acc_status='defence_off'
		elif s0[-4:-6]=='11':
			acc_status='defence_on'

		if s0[-6:-8]=='10':
			acc_status='oil_ele_off'
		elif s0[-6:-8]=='11':
			acc_status='oil_ele_on'

		if s0[-6:-8]=='10':
			acc_status='charge_off'
		elif s0[-6:-8]=='11':
			acc_status='charge_on'

		

		gsm_status=data_result['gsm']
		gsm_dict={'01':'gsm_singal_no','02':'gsm_singal_week+','03':'gsm_singal_week','04':'gsm_singal_normal','04':'gsm_singal_good'}
		gsm_status=gsm_dict[gsm_status]
		
		
		status=str([track_status,acc_status,defence,oil_ele,charge,gsm_status])
		all_data['status']=status
		all_data['battery']=data_result['battery']

	elif mesg_id=='08':
		time_data=time.time()
		time_data='%08x' % time_data
		all_data['chack_time']='chack_time'

		response='6767'+mesg_id+'0006'+head_data['data_num']+time_data
		response=bytes.fromhex(response)

	elif mesg_id=='09':
		all_data['iccid']=int(str(data_detail))

	elif mesg_id=='0c':
		rule=r'(?P<mesg_count>\w{2})(?P<mesg_num>\w{2})(?P<time_data>\w{12})'
		first_data=re.search(rule,data_detail)
		# print(first_data.groupdict())
		time_data=first_data.groupdict()['time_data']
		mesg_count=first_data.groupdict()['mesg_count']
		mesg_num=first_data.groupdict()['mesg_num']
		all_pack=int(mesg_count,16)-1
		this_pack=int(mesg_num,16)
		# response=response+bytes.fromhex(mesg_num+time_data)

		response='6767'+mesg_id+'0009'+head_data['data_num']+mesg_num+time_data
		response=bytes.fromhex(response)

		if all_pack==this_pack:
			second_data=data_detail[len(first_data.group()):]
			all_data['end_separate']={this_pack:second_data}
			all_data['separate_kind']='tk_mesg'
			# print('voice----end',all_pack,this_pack,len(second_data))
		else:
			second_data=data_detail[len(first_data.group()):]
			all_data['separate_package']={this_pack:second_data}
			# print('voice----add',all_pack,this_pack,len(second_data),len(data_detail),first_data.group(),len(first_data.group()))

	elif mesg_id=='0a':
		record_dict={'00':'success','01':'recording','03':'record_failed','02':'error'}
		all_data['open_record_result']=record_dict[data_detail]
		response=b'0'

	elif mesg_id=='0b':
		record_dict={'00':'success','01':'close_failed','03':'no_record','02':'error'}
		all_data['colse_record_result']=record_dict[data_detail]
		response=b'0'

	elif mesg_id=='fe':
		all_data['through_data']=data_detail

	elif mesg_id=='92':
		rule=r'(?P<time_data>\w{8})(?P<wifi_num>\w{2})(?P<wifi_detail>\w*)'

		data_result=re.search(rule,data_detail).groupdict()
		data_result['time_data']=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(float(data_result['time_data'])))
		wifi_num=data_result['wifi_num']
		wifi_detail=data_result['wifi_detail']
		wifi_list=[]

		if len(wifi_detail)%7!=0:
			wifi_detail=wifi_detail[0:len(wifi_detail)-len(wifi_detail)%7]

		for x in range(int(wifi_num)):
			wifi_data=wifi_detail[x*7:(x+1)*7]
			wifi_mac=wifi_data[0:2]+':'+wifi_data[2:4]+':'+wifi_data[4:6]+':'+wifi_data[6:8]+':'+wifi_data[8:12]
			wifi_dict={'mac':wifi_mac,'rssi':wifi_data[12:14],'ssid':'no_ssid'}
			wifi_list.append(wifi_dict)

		all_data['wifi']=str(wifi_list)

	elif mesg_id=='0d':

		def get_dev_status(data_detail):
			rule=r'(?P<data_tag>\w{2})(?P<value_len>\w{2})'
			data_result=re.search(rule,data_detail).groupdict()
			tag_dict={'01':'accurate','02':'record_status','03':'record_volume','04':'battery'}
			data_tag=data_result['data_tag']
			value_len=data_result['value_len']
			this_len=4+int(value_len,16)*2
			this_data=data_detail[0:this_len]

			all_data[tag_dict[data_tag]]=this_data[4:]

			left_data=data_detail[this_len:]
			if left_data!='':
				get_dev_status(left_data)

			return None

		get_dev_status(data_detail)

		response=b'0'

	elif mesg_id=='80':
		rule=r'(?P<param_id>\w{2})(?P<serv_id>\w{8})'
		data_result=re.search(rule,data_detail).groupdict()
		param_id=data_result['param_id']
		serv_id=data_result['serv_id']
		param_value=data_detail[10:]

		def handle_where(param_value):
			param_value=bytes.fromhex(param_value)
			param_value=param_value.decode()
			param_value=param_value.split(',')
			all_data['lat']=param_value[0].split(':')[1]
			all_data['lng']=param_value[1].split(':')[1]
			all_data['speed']=param_value[2].split(':')[1]
			all_data['dirct']=param_value[3].split(':')[1]

			def get_value_num(str_num):
				handle_rule=r'(?P<value_num>\d*)'
				value_num=re.match(handle_rule,str_num).groupdict()['value_num']
				return value_num

			all_data['speed']=get_value_num(all_data['speed'])
			all_data['dirct']=get_value_num(all_data['dirct'])

		param_id_dict={'00000001': 'query_param', '00000002': 'call_now', '00000003': 'query_verson', 
					   '00000004': 'query_status', '00000005': 'factory', '00000006': 'reset', 
					   '00000007': 'cut_oil', '00000008': 'send_rate', '00000009': 'wakeup', 
					   '00000010': 'set_time_zone', '00000011': 'query_time_zone', '00000012': 'language', 
					   '00000013': 'center_num_set', '00000014': 'query_center_num', '00000015': 'sos', 
					   '00000016': 'query_sos', '00000017': 'query_sos_alarm', '00000018': 'sos_set', 
					   '00000019': 'dev_remove_alarm', '00000020': 'query_remove_alarm', '00000021': 'low_power_alarm',
					   '00000022': 'query_low_power_alarm', '00000023': 'query_poweroff_set', '00000024': 'poweroff_set',
					   '00000025': 'query_sensor_set', '00000026': 'sensor_set', '00000027': 'query_gpson', 
					   '00000028': 'gpson', '00000029': 'query_defence', '00000030': 'defence', '00000031': 'sensitivity', 
					   '00000032': 'query_static_speed_drop', '00000033': 'static_speed_drop','00000034':'query_gprs_set'}

		data_kind=param_id_dict[serv_id]

		if data_kind=='call_now':
			handle_where(param_value)
		else:
			param_value=bytes.fromhex(param_value)
			param_value=param_value.decode()
			all_data[data_kind]=param_value
			all_data['command_name']=data_kind
			all_data['command_result']=param_value

			
	all_data['response']=response
	# print(all_data)
	print('analysis_end-----')
	return all_data


# td=b'gg\x04\x00\x1e\x15}^\x0f%S\x02m.\x84\x0c<\r\x80\x00\x00\xe9\x01\xcc\x00\x00$\xa4\x00\x11\x96\x00\x10\x00\x00'
# td=bytes.hex(td)
# print(gumi_analysis(td))




